using System;
using AnjLab.SyncIT.Core.Api;

namespace AnjLab.SyncIT.Core.Api
{
    public class Source : IEquatable<Source>
    {
        protected bool _paused;
        public virtual event EventHandler PausedChanged;
        public string ProviderKey { get; set;}
        public string ProjectBase { get; set;}
        
        public string PasswordHash { get; set; }

        public string Password
        {
            get { return null; }
            set
            {
                if (value != null)
                {
                    SetPassword(value);
                }
            }
        }

        public void SetPassword(string value)
        {
            PasswordHash = value == null ? null : CryptographyTool.Encrypt(value);
        }

        public string GetPassword()
        {
            return PasswordHash == null ? null : CryptographyTool.Decrypt(PasswordHash);
        }

        public Provider GetProvider()
        {
            return Provider.Get(ProviderKey);
        }

        public string Icon
        {
            get { return GetProvider().Icon; }
        }

        public bool HasPassword {
            get { return GetProvider().HasPassword; }
        }

        private ISourceTaskDao cachedDao;
        //  In case source settings were changed
        private int cachedHashCode;
        
        public ISourceTaskDao GetTaskDao() {
            if (cachedDao != null && cachedHashCode == GetHashCode())
            {
                return cachedDao;
            }

            var result = GetProvider().CreateTaskDao(this);

            if (GetProvider().MayChacheTaskDao)
            {
                cachedDao = result;
                cachedHashCode = GetHashCode();
            }

            return result;
        }

        /// <summary>
        /// Fix for Issue #22
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void ReleaseCache(object sender, FX.Sys.EventArgs<Source, string> e)
        {
            e.Item1.cachedDao = null;
        }

        public string GetMyTasksUrl()
        {
            return GetProvider().GetMyTasksUrl(this);
        }

        public string GetActiveTasksUrl() {
            return GetProvider().GetActiveTasksUrl(this);
        }

        public virtual string Title
        {
            get { return GetProvider().GetTitle(this); }
        }

        public bool Paused {
            get { return _paused; }
            set {
                if (_paused == value) return;
                _paused = value;
                if (PausedChanged != null)
                    PausedChanged(this, EventArgs.Empty);
            }
        }

        public virtual string UserName { get; set; }

        public DateTime SyncTimestamp { get; set; }

        public bool CustomizeBody { get; set; }
        public string BodyTemplate { get; set; }

        public bool CustomizeSubject { get; set; }
        public string SubjectTemplate { get; set; }

        private string _outlookCategory;

        public string ProjectBaseHint
        {
            get { return GetProvider().GetProjectBaseHint(this); }
        }
        public string UserNameHint
        {
            get { return GetProvider().GetUserNameHint(this); }
        }
        public string PasswordHint
        {
            get { return GetProvider().GetPasswordHint(this); }
        }
        public string OutlookPrefixHint
        {
            get { return GetProvider().GetOutlookPrefixHint(this); }
        }
        public string OutlookCategoryHint
        {
            get { return GetProvider().GetOutlookCategoryHint(this); }
        }

        public string OutlookCategory
        {
            get { return _outlookCategory; }
            set
            {
                if (value != _outlookCategory)
                {
                    _outlookCategory = value;

                    if (OutlookCategoryChanged != null)
                    {
                        OutlookCategoryChanged(this, EventArgs.Empty);
                    }
                }
            }
        }

        public OutlookDestination OutlookDestination { get; set; }
        
        public event EventHandler OutlookCategoryChanged;

        public string OutlookPrefix { get; set; }

        public object Clone()
        {
            return MemberwiseClone();
        }

        public bool Equals(Source source)
        {
            if (source == null) return false;
            //  Compare only configuration parameters of the source that user configures through UI
            return Equals(ProviderKey, source.ProviderKey)
                && Equals(ProjectBase, source.ProjectBase)
                && Equals(UserName, source.UserName)
                && Equals(GetPassword(), source.GetPassword())
                && Equals(_outlookCategory, source._outlookCategory);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj)) return true;
            return Equals(obj as Source);
        }

        public override int GetHashCode()
        {
            return 29 * (ProviderKey != null ? ProviderKey.GetHashCode() : 0)
                 + 21 * (ProjectBase != null ? ProjectBase.GetHashCode() : 0)
                 + 17 * (UserName != null ? UserName.GetHashCode() : 0)
                 + 13 * (GetPassword() != null ? GetPassword().GetHashCode() : 0)
                 + 02 * (_outlookCategory != null ? _outlookCategory.GetHashCode() : 0)
                ;
        }
    }

    public enum OutlookDestination
    {
        TaskList,
        Calendar
    }
}